﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;
using System.Drawing.Imaging;

using FourierTools.DSP;

namespace LowLevelGraphics
{
    public class UnsafeFourierBitmap
    {
        /// <summary>
        /// Initializes a new instance of the <see cref="UnsafeFourierBitmap"/> class.
        /// </summary>
        /// <param name="_sFileName">Name of the _s file.</param>
        public UnsafeFourierBitmap(string _sFileName)
            : this(new Bitmap(_sFileName))
        {
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="UnsafeFourierBitmap"/> class.
        /// </summary>
        /// <param name="_bitmap">The _bitmap.</param>
        public unsafe UnsafeFourierBitmap(UnsafeBitmap _bitmap)
        {
            UnsafeBitmap bitmap = _bitmap;
            
            Size correctSize = new Size(
                (int)Math.Pow(2, Math.Ceiling(Math.Log(bitmap.Width, 2))),
                (int)Math.Pow(2, Math.Ceiling(Math.Log(bitmap.Height, 2))));

            if (correctSize != bitmap.Size)
            {//TODO: correct
                //bitmap = new UnsafeBitmap(bitmap, correctSize);
            }

            size = correctSize;
            aData = new ComplexF[this.Width * this.Height];
            Rectangle rect = new Rectangle(0, 0, this.Width, this.Height);
            //BitmapData bitmapData = bitmap.LockBits(rect, ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);
            int* colorData = (int*)bitmap.BitmapData.Scan0.ToPointer();
            for (int i = 0; i < this.Width * this.Height; i++)
            {
                Color color = Color.FromArgb(colorData[i]);
                aData[i].Re = ((float)color.R + (float)color.G + (float)color.B) / (3f * 256f);
            }
        }

        //--------------------------------------------------------------------------------------

        /// <summary>
        /// 
        /// </summary>
        protected ComplexF[] aData = null;
        /// <summary>
        /// Gets the data.
        /// </summary>
        /// <value>The data.</value>
        public ComplexF[] Data
        {
            get { return aData; }
        }

        protected bool _frequencySpace = false;
        /// <summary>
        /// Gets or sets a value indicating whether [frequency space].
        /// </summary>
        /// <value><c>true</c> if [frequency space]; otherwise, <c>false</c>.</value>
        public bool FrequencySpace
        {
            get { return _frequencySpace; }
            set { _frequencySpace = value; }
        }

        protected Size size = Size.Empty;
        /// <summary>
        /// Gets the size.
        /// </summary>
        /// <value>The size.</value>
        public Size Size
        {
            get { return size; }
        }

        /// <summary>
        /// Gets the width.
        /// </summary>
        /// <value>The width.</value>
        public int Width
        {
            get { return size.Width; }
        }

        /// <summary>
        /// Gets the height.
        /// </summary>
        /// <value>The height.</value>
        public int Height
        {
            get { return size.Height; }
        }

        //--------------------------------------------------------------------------------------

        /// <summary>
        /// Toes the bitmap.
        /// </summary>
        /// <returns></returns>
        public unsafe Bitmap ToBitmap()
        {
            Bitmap bitmap = new Bitmap(this.Width, this.Height, PixelFormat.Format32bppArgb);
            Rectangle rect = new Rectangle(0, 0, this.Width, this.Height);
            BitmapData bitmapData = bitmap.LockBits(rect, ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb);
            int* colorData = (int*)bitmapData.Scan0.ToPointer();
            for (int i = 0; i < this.Width * this.Height; i++)
            {
                int nColorValue = Math.Min(255, Math.Max(0, (int)(256 * aData[i].GetModulus())));
                colorData[i] = Color.FromArgb(nColorValue, nColorValue, nColorValue).ToArgb();
            }
            bitmap.UnlockBits(bitmapData);
            return bitmap;
        }

        /// <summary>
        /// Saves the specified file name.
        /// </summary>
        /// <param name="fileName">Name of the file.</param>
        public void Save(string fileName)
        {
            this.ToBitmap().Save(fileName);
        }

        //--------------------------------------------------------------------------------------

        /// <summary>
        /// Releases unmanaged and - optionally - managed resources
        /// </summary>
        public void Dispose()
        {
        }

    }
}